package util.ir;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.RAMDirectory;

import util.models.LanguageModel;

public class LMSearcher {

	String index_path = "/home/sergio/index/LM_trigrams";

	private String fields_trigrams[] = { "a", "b", "c", "f_t", "f_seed",
			"f_12", "f_23", "f_13" };

	private String fields_trigrams_simple[] = { "trigram", "f_t", "f_seed",
			"f_12", "f_23", "f_13" };

	private String fields_bigrams[] = { "a", "b", "f_b", "f_seed", "f_1", "f_2" };
	private String fields_bigrams_simple[] = { "bigram", "f_b", "f_seed",
			"f_1", "f_2" };

	private String index = "";

	private IndexSearcher searcher = null;
	Analyzer analyzer = new WhitespaceAnalyzer();

	public LMSearcher(String index) throws IOException {
		this.index = index;

		RAMDirectory dir = new RAMDirectory(index);
		searcher = new IndexSearcher(dir);
		System.out.println("Loaded index into memory");

	}

	public HashSet<String[]> trigramSearchSimple(HashSet<String> ts)
			throws CorruptIndexException, IOException, ParseException {

		QueryParser queryParser = new QueryParser("trigram", analyzer);
		// <default field> is the field that QueryParser will search if you
		// don't
		// prefix it with a field.

		String query = "";

		Iterator<String> iter = ts.iterator();

		while (iter.hasNext()) {

			query = query + iter.next() + "\t";
		}

		/*
		 * for (int i = 0; i < t.length; i++) {
		 * 
		 * query = query + t[i] + "\t";
		 * 
		 * }
		 */
		query = query.trim();

		// Matching

		Hits hits = searcher.search(queryParser.parse(query));
		HashSet<String[]> response = new HashSet<String[]>();

		for (int i = 0; i < hits.length(); i++) {

			Document doc = hits.doc(i);

			String r[] = new String[fields_trigrams_simple.length];
			String temp = "";

			String buffer_b = "";
			boolean matched_right_place = false;
			boolean should_swap = false;

			for (int j = 0; j < fields_trigrams_simple.length; j++) {
				String value = doc.get(fields_trigrams_simple[j]);

				if (fields_trigrams_simple[j].equals("b")) {
					if (ts.contains(value)) {

						matched_right_place = true;
						r[j] = value;
					} else {
						r[j] = value;
						buffer_b = value;
						should_swap = true;
					}

				} else if (fields_trigrams_simple[j].equals("c")) {

					if (should_swap) {
						if (ts.contains(value)) {
							r[j - 1] = value;
							r[j] = buffer_b;
							matched_right_place = true;
						} else {

							r[j] = value;
						}

					}

				} else {

					r[j] = value;
				}

				temp = temp + r[j] + "\t";

			}

			if (matched_right_place) {
				response.add(r);
				// System.out.println(temp);
			}
		}

		// swap answers here c for b and b for c
		System.out.println(response.size());
		response.clear();
		searcher.close();
		return response;

	}

	public void trigramSearchLM(HashSet<String> ts, LanguageModel lm)
			throws CorruptIndexException, IOException, ParseException {

		QueryParser queryParser = new QueryParser("trigram", analyzer);
		// <default field> is the field that QueryParser will search if you
		// don't
		// prefix it with a field.

		String query = "";

		Iterator<String> iter = ts.iterator();

		while (iter.hasNext()) {

			query = query + iter.next() + "\t";
		}

		query = query.trim();

		// Matching
		// System.out.println(queryParser + "\t" + query + "\t"+ searcher);
		Hits hits = searcher.search(queryParser.parse(query));
		HashSet<String[]> response = new HashSet<String[]>();

		for (int i = 0; i < hits.length(); i++) {

			Document doc = hits.doc(i);

			String r[] = new String[fields_trigrams.length];

			boolean matched_right_place = false;

			int index = 0;

			String terms = doc.get(fields_trigrams_simple[0]);
			String terms_s[] = terms.split("\t");

			for (int k = 0; k < terms_s.length; k++) {

				r[k] = terms_s[k];
				index++;
			}

			for (int j = index; j < fields_trigrams.length; j++) {
				String value = doc.get(fields_trigrams[j]);
				r[j] = value;

			}

			matched_right_place = orderFields(r, ts);
			
			if (matched_right_place) {
				String temp = "";
				for (int l = 0; l < r.length; l++) {

					temp = temp + r[l] + "\t";
				}
				// System.out.println(matched_right_place + "\t" + temp);
				 
				 
			//	System.out.println(temp);
				addLineToLM(r, lm);
				response.add(r);
				// System.out.println(temp);
			}
		}

		System.out.println("Found: " + response.size());
	}

	public void bigramSearchLM(HashSet<String> ts, LanguageModel lm)
			throws CorruptIndexException, IOException, ParseException {

		QueryParser queryParser = new QueryParser("bigram", analyzer);
		// <default field> is the field that QueryParser will search if you
		// don't
		// prefix it with a field.

		String query = "";

		Iterator<String> iter = ts.iterator();

		while (iter.hasNext()) {

			query = query + iter.next() + "\t";
		}

		query = query.trim();

		// Matching
		// System.out.println(queryParser + "\t" + query + "\t"+ searcher);
		Hits hits = searcher.search(queryParser.parse(query));

		HashSet<String[]> response = new HashSet<String[]>();

		for (int i = 0; i < hits.length(); i++) {

			Document doc = hits.doc(i);

			String r[] = new String[fields_bigrams.length];

			boolean matched_right_place = false;

			int index = 0;

			String terms = doc.get(fields_bigrams_simple[0]);
			String terms_s[] = terms.split("\t");

			for (int k = 0; k < terms_s.length; k++) {

				r[k] = terms_s[k];
				index++;
			}

			for (int j = index; j < fields_bigrams.length; j++) {
				String value = doc.get(fields_bigrams[j]);
				r[j] = value;

			}

			matched_right_place = orderFieldsBigram(r, ts);
			matched_right_place = true;

			/*
			 * For now, revized this!!!!!!!!!!
			 */

			// System.out.println(matched_right_place + "\t" + terms);
			if (matched_right_place) {
				String temp = "";
				for (int l = 0; l < r.length; l++) {

					temp = temp + r[l] + "\t";
				}

				// System.out.println(temp);
				addBigramLineToLM(r, lm);
				response.add(r);
				// System.out.println(temp);
			}
		}

		System.out.println("Found: " + response.size());
		response.clear();

	}

	// swap answers here c for b and b for c

	// searcher.close();

	private boolean orderFields(String[] r, HashSet<String> ts) {
		// TODO Auto-generated method stub

		// "a", "b", "c", "f_t", "f_seed", "f_12", "f_23", "f_13"

		// check if match in second position, then no changes needed

		if (ts.contains(r[1])) {
		
			return true;
		} else if (ts.contains(r[2])) {
		
			// swap c and b and frequencies
			
			String buf = r[1];
			r[1] = r[2];
			r[2] = buf;

			buf = r[5];
			r[5] = r[7];
			r[7] = buf;
			
			return true;

		} else {

			return false;
		}

		// check for math in third position

		

	}

	private boolean orderFieldsBigram(String[] r, HashSet<String> ts) {
		// TODO Auto-generated method stub

		// "a", "b", "c", "f_t", "f_seed", "f_12", "f_23", "f_13"
		// "a", "b", "f_b", "f_seed", "f_1", "f_2"
		// check if match in second position, then no changes needed

		if (ts.contains(r[1])) {

			return true;
		}

		return false;

	}

	public void close() {

		try {
			searcher.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void addLineToLM(String[] r, LanguageModel lm) {
		// TODO Auto-generated method stub

		String k = r[0];
		String s = r[2];
		String t = r[1];
		// { "a", "b", "c", "f_t", "f_seed","f_12", "f_23", "f_13" };

		Integer freq_t = Integer.valueOf(r[3]);
		Integer freq_ks = Integer.valueOf(r[5]);
		Integer freq_st = Integer.valueOf(r[6]);
		Integer freq_kt = Integer.valueOf(r[7]);
		Integer freq_seed = Integer.valueOf(r[4]);

		lm.addTrigram(s, k, t, freq_t);

		lm.addBigram(s, k, freq_ks);
		lm.addBigram(s, t, freq_st);
		lm.addBigram(k, t, freq_kt);

		// add unigrams

		lm.addUnigram(k, freq_seed);
		
		lm.seeds.put(k, Float.valueOf(freq_seed));

	}

	private void addBigramLineToLM(String[] r, LanguageModel lm) {
		// TODO Auto-generated method stub

		String k = r[0];
		String s = r[1];

		// "a", "b", "f_b", "f_seed", "f_1", "f_2" ;
		// { "a", "b", "c", "f_t", "f_seed","f_12", "f_23", "f_13" };

		for(int i =0 ; i<r.length; i++){
			
			System.out.println(r[i]);
		}
		Integer freq_t = Integer.valueOf(r[2]);
		Integer freq_k = Integer.valueOf(r[4]);
		Integer freq_s = Integer.valueOf(r[5]);
		Integer freq_seed = Integer.valueOf(r[3]);

		lm.addBigram(k,s, freq_t);
		lm.addUnigram(k, freq_k);
		lm.addUnigram(s, freq_s);

		// add unigrams
		// lm.addUnigram(k, freq_seed);
		//lm.seeds.put(k, Float.valueOf(freq_seed));

	}

	public static void main(String args[]) throws ParseException {

		/*
		 * try { LMSearcher lm = new LMSearcher(
		 * "/home/sergio/delicious_index/trigrams_index_filter2");
		 * 
		 * HashSet<String> query = new HashSet<String>();
		 * 
		 * query.add("games"); query.add("toys"); query.add("flash");
		 * query.add("kids");
		 * 
		 * LanguageModel lmodel = new LanguageModel(); lm.trigramSearchLM(query,
		 * lmodel);
		 * 
		 * } catch (IOException e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); }
		 */

		try {
			LMSearcher lm = new LMSearcher(
					"/home/sergio/delicious_index/bigrams_index_filter2");

			HashSet<String> query = new HashSet<String>();

			query.add("games");
			query.add("toys");
			query.add("flash");
			query.add("kids");

			LanguageModel lmodel = new LanguageModel();
			lm.bigramSearchLM(query, lmodel);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
